<?php
namespace app\common\lib\pay\wxpay;
require_once 'WxPay.Api.php';
/**
 *
 * H5Pay支付实现类
 * 该类实现了从微信公众平台获取code、通过code获取openid和access_token、
 * 生成h5支付js接口所需的参数、生成获取共享收货地址所需的参数
 *
 * 该类是微信支付提供的样例程序，商户可根据自己的需求修改，或者使用lib中的api自行开发
 *
 * @author widy
 *
 */
class H5Pay
{
    /**
     *
     * 网页授权接口微信服务器返回的数据，返回样例如下
     * {
     *  "access_token":"ACCESS_TOKEN",
     *  "expires_in":7200,
     *  "refresh_token":"REFRESH_TOKEN",
     *  "openid":"OPENID",
     *  "scope":"SCOPE",
     *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * }
     * 其中access_token可用于获取共享收货地址
     * openid是微信支付jsapi支付接口必须的参数
     * @var array
     */
    public $data = null;

    /**
     *
     * 通过跳转获取用户的openid，跳转流程如下：
     * 1、设置自己需要调回的url及其其他参数，跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
     * 2、微信服务处理完成之后会跳转回用户redirect_uri地址，此时会带上一些参数，如：code
     *
     * @return 用户的openid
     */
    public function GetOpenid()
    {
        //通过code获得openid
        if (!isset($_GET['code'])) {
            //触发微信返回code码
            $http_type =
                (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
                (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
                    $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
                    ? 'https://'
                    : 'http://';
            $baseUrl = $http_type . $_SERVER['HTTP_HOST'];
            if (isset($_SERVER['REQUEST_URI'])) {
                $baseUrl .= $_SERVER['REQUEST_URI'];
            } else {
                if (isset($_SERVER['argv'])) {
                    $baseUrl .= '?' . $_SERVER['argv'][0];
                } else {
                    $baseUrl .= '?' . $_SERVER['QUERY_STRING'];
                }
            }
            $baseUrl = rtrim($baseUrl, C('URL_HTML_SUFFIX'));
            $baseUrl = urlencode($baseUrl);
            $url = $this->__CreateOauthUrlForCode($baseUrl);
            Header("Location: $url");
            exit();
        } else {
            //获取code码，以获取openid
            $code = $_GET['code'];
            $openid = $this->getOpenidFromMp($code);
            return $openid;
        }
    }

    /**
     *
     * 获取jsapi支付的参数
     * @param array $UnifiedOrderResult 统一支付接口返回的数据
     * @throws WxPayException
     *
     * @return json数据，可直接填入js函数作为参数
     */
    public function GetJsApiParameters($UnifiedOrderResult)
    {
        if (
            !array_key_exists('appid', $UnifiedOrderResult) ||
            !array_key_exists('prepay_id', $UnifiedOrderResult) ||
            $UnifiedOrderResult['prepay_id'] == ''
        ) {
            throw new WxPayException('参数错误');
        }
        $jsapi = new WxPayJsApiPay();
        $jsapi->SetAppid($UnifiedOrderResult['appid']);
        $timeStamp = time();
        $jsapi->SetTimeStamp($timeStamp . '');
        $jsapi->SetNonceStr(WxPayApi::getNonceStr());
        $jsapi->SetPackage('prepay_id=' . $UnifiedOrderResult['prepay_id']);
        $jsapi->SetSignType('MD5');
        $jsapi->SetPaySign($jsapi->MakeSign());
        $parameters = json_encode($jsapi->GetValues());
        return $parameters;
    }

    /**
     *
     * 通过code从工作平台获取openid机器access_token
     * @param string $code 微信跳转回来带上的code
     *
     * @return openid
     */
    public function GetOpenidFromMp($code)
    {
        $url = $this->__CreateOauthUrlForOpenid($code);
        //初始化curl
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOP_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        if (
            WxPayConfig::CURL_PROXY_HOST != '0.0.0.0' &&
            WxPayConfig::CURL_PROXY_PORT != 0
        ) {
            curl_setopt($ch, CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
            curl_setopt($ch, CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
        }
        //运行curl，结果以jason形式返回
        $res = curl_exec($ch);
        curl_close($ch);
        //取出openid
        $data = json_decode($res, true);
        $this->data = $data;
        $openid = $data['openid'];
        return $openid;
    }

    /**
     *
     * 拼接签名字符串
     * @param array $urlObj
     *
     * @return 返回已经拼接好的字符串
     */
    private function ToUrlParams($urlObj)
    {
        $buff = '';
        foreach ($urlObj as $k => $v) {
            if ($k != 'sign') {
                $buff .= $k . '=' . $v . '&';
            }
        }

        $buff = trim($buff, '&');
        return $buff;
    }

    /**
     *
     * 获取地址js参数
     *
     * @return 获取共享收货地址js函数需要的参数，json格式可以直接做参数使用
     */
    public function GetEditAddressParameters()
    {
        $getData = $this->data;
        $data = array();
        $data['appid'] = WxPayConfig::$appid;
        $http_type =
            (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
            (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
                $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
                ? 'https://'
                : 'http://';
        $data['url'] =
            $http_type . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        $time = time();
        $data['timestamp'] = "$time";
        $data['noncestr'] = '1234568';
        $data['accesstoken'] = $getData['access_token'];
        ksort($data);
        $params = $this->ToUrlParams($data);
        $addrSign = sha1($params);

        $afterData = array(
            'addrSign' => $addrSign,
            'signType' => 'sha1',
            'scope' => 'jsapi_address',
            'appId' => WxPayConfig::$appid,
            'timeStamp' => $data['timestamp'],
            'nonceStr' => $data['noncestr']
        );
        $parameters = json_encode($afterData);
        return $parameters;
    }

    /**
     *
     * 构造获取code的url连接
     * @param string $redirectUrl 微信服务器回跳的url，需要url编码
     *
     * @return 返回构造好的url
     */
    private function __CreateOauthUrlForCode($redirectUrl)
    {
        $urlObj['appid'] = WxPayConfig::$appid;
        $urlObj['redirect_uri'] = "$redirectUrl";
        $urlObj['response_type'] = 'code';
        $urlObj['scope'] = 'snsapi_base';
        $urlObj['state'] = 'STATE' . '#wechat_redirect';
        $bizString = $this->ToUrlParams($urlObj);
        return 'https://open.weixin.qq.com/connect/oauth2/authorize?' .
            $bizString;
    }

    /**
     *
     * 构造获取open和access_toke的url地址
     * @param string $code，微信跳转带回的code
     *
     * @return 请求的url
     */
    private function __CreateOauthUrlForOpenid($code)
    {
        $urlObj['appid'] = WxPayConfig::$appid;
        $urlObj['secret'] = WxPayConfig::$appsecret;
        $urlObj['code'] = $code;
        $urlObj['grant_type'] = 'authorization_code';
        $bizString = $this->ToUrlParams($urlObj);
        return 'https://api.weixin.qq.com/sns/oauth2/access_token?' .
            $bizString;
    }
}
